#pragma once

#include <gofcl_spi_ctl0.h>

// CTL0寄存器CKPH、CKPL位的取值：不传输时时钟高还是低、哪个时钟沿采集。
typedef enum {
	SPI_CLK_IDLE_LOW_CAPT_UP = 0,
	SPI_CLK_IDLE_LOW_CAPT_DOWN = 1,
	SPI_CLK_IDLE_HIGH_CAPT_DOWN = 2,
	SPI_CLK_IDLE_HIGH_CAPT_UP = 3,
} spi_clk_seq_e;

// CTL0寄存器MSTMOD位的取值：SPI工作在主机还是从机模式。
typedef enum {
	SPI_SLAVE_MODE = 0,
	SPI_MASTER_MODE = 1,
} spi_ms_mode_e;

// CTL0寄存器PSC位的取值：SPI工作在主机还是从机模式。
typedef enum {
	SPI_PSC_DIV_2 = 0,
	SPI_PSC_DIV_4 = 1,
	SPI_PSC_DIV_8 = 2,
	SPI_PSC_DIV_16 = 3,
	SPI_PSC_DIV_32 = 4,
	SPI_PSC_DIV_64 = 5,
	SPI_PSC_DIV_128 = 6,
	SPI_PSC_DIV_256 = 7,
} spi_psc_e;

// CTL0寄存器LF位的取值：发送数据时先发低位还是高位。
typedef enum {
	SPI_MSB_FIRST = 0,
	SPI_LSB_FIRST = 1,
} spi_lsb_msb_first_e;

// CTL0寄存器SWNSSEN位的取值：硬件NSS/软件NSS。
typedef enum {
	SPI_NSS_HARD = 0,
	SPI_NSS_SOFT = 1,
} spi_nss_mode_e;

// CTL0寄存器FF16位的取值：每次发送数据长度为8位还是16位。
typedef enum {
	SPI_DATA_8_BIT = 0,
	SPI_DATA_16_BIT = 1,
} spi_data_len;

// CTL0寄存器CRCNT位的取值：（下一个）传输的是普通数据还是CRC。
typedef enum {
	SPI_NEXT_NORMAL = 0,
	SPI_NEXT_CRC = 1,
} spi_next_type_e;

// CTL0寄存器BDOEN位的取值：半双工（数据）传输方向。
typedef enum {
	SPI_HDX_IN = 0,
	SPI_HDX_OUT = 1,
} spi_hdx_dir_e;

// CTL0寄存器BDEN位的取值：全双工/半双工。
typedef enum {
	SPI_FULL_DUPLEX = 0,
	SPI_HALF_DUPLEX = 1,
} spi_full_half_duplex_e;

typedef struct {
	__attribute__((packed)) spi_clk_seq_e clk_seq : 2;
	__attribute__((packed)) spi_ms_mode_e ms_mode : 1;
	__attribute__((packed)) spi_psc_e clk_psc : 3;
	u16_s spi_en : 1;
	__attribute__((packed)) spi_lsb_msb_first_e lsb_msb_first : 1;
	u16_s sw_nss_level : 1;
	__attribute__((packed)) spi_nss_mode_e nss_mode : 1;
	u16_s read_only : 1;
	__attribute__((packed)) spi_data_len data_len : 1;
	__attribute__((packed)) spi_next_type_e next_type : 1;
	u16_s crc_en : 1;
	__attribute__((packed)) spi_hdx_dir_e hdx_dir : 1;
	__attribute__((packed)) spi_full_half_duplex_e full_half_duplex : 1;
} spi_ctl0_expl_s;

_Static_assert(sizeof(spi_ctl0_expl_s) == 2,
	       "Struct spi_ctl0_expl_s defined error!");

static inline void spi_set_ctl0(spi_qe spi_q, spi_ctl0_expl_s ctl0) {
	union {
		spi_ctl0_s c;
		spi_ctl0_expl_s e;
	} cu = {
		.e = ctl0,
	};
	spi_wreg_ctl0_s(spi_q, cu.c);
}
